
package com.x52im.rbchat.logic.sns_group;

import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.eva.android.ToolKits;
import com.eva.android.widget.DataLoadableActivity2;
import com.eva.android.widget.WidgetUtils;
import com.eva.android.widget.alert.AlertDialog;
import com.eva.epc.common.util.CommonUtils;
import com.eva.framework.dto.DataFromServer;
import com.x52im.rbchat.MyApplication;
import com.x52im.rbchat.R;
import com.x52im.rbchat.cache.ImageCacheLoader;
import com.x52im.rainbowchat.http.logic.dto.GroupEntity;
import com.x52im.rainbowchat.http.logic.dto.RosterElementEntity;
import com.x52im.rbchat.logic.chat_group.utils.GChatDataHelper;
import com.x52im.rbchat.logic.qrcode.utils.QRCodeScheme;
import com.x52im.rbchat.logic.sns_group.viewmodel.JoinGroupViewModel;
import com.x52im.rbchat.network.http.HttpRestHelper;
import com.x52im.rbchat.utils.IntentFactory;

import java.util.ArrayList;

import androidx.lifecycle.ViewModelProvider;

/**
 * 加入群聊界面实现类（当前用于扫描加群二维码和群名片加群时）。
 *
 * @author JackJiang
 * @since 8.1
 */
public class JoinGroupActivity extends DataLoadableActivity2 {

    private final static String TAG = JoinGroupActivity.class.getSimpleName();

    /** 加群方式：通过扫描二维码加群 */
    public final static int JOIN_BY_SCAN_QRCODE = 0;
    /** 加群方式：通过分享的群名片加群 */
    public final static int JOIN_BY_GROUP_CONTACT = 1;

    /** intent中传过来的gid */
    private String gid = null;
    /** intent中传过来的分享者uid */
    private String sharedByUid = null;
    /** intent中传过来的加群途径 */
    private int joinBy = JOIN_BY_SCAN_QRCODE;

    /** 对应的群基本信息 */
    private GroupEntity groupInfo = null;
    /** 对应的2维码分享者用户资料 */
    private RosterElementEntity sharedByUser = null;

    /** 群头像显示组件 */
    private ImageView viewIcon = null;
    /** 群名称显示组件 */
    private TextView viewName = null;
    /** 群描述显示组件 */
    private TextView viewDesc = null;
    /** 确认按钮 */
    private Button btnOk = null;

    /** 本界面对应的ViewModel实现类 */
    private JoinGroupViewModel viewModel;

    /**
     * 父类的onCreate方法调用后将要调用的方法（默认本方法什么也不做）。
     * <p>
     * 本方法将在{@link #init(Bundle)}方法前调用，子类可以在此实现{@link #init(Bundle)}方法前需要逻辑。<br>
     * 本方法中建议尽量不涉及UI代码逻辑，UI代码逻辑请在 {@link #init(Bundle)}方法及其子方法中实现。
     */
    @Override
    protected void onCreateAfter(){
        // 拿到本类对应的ViewModel对象，实现MVVM架构
        viewModel = new ViewModelProvider(this).get(JoinGroupViewModel.class);
    }

    /**
     * 解析从Intent中传过来的可能的数据本方法中实现.
     * 例如从上一个activity中传过来的数据，本方法被 {@link #init(Bundle)}调用。
     *
     * @see QRCodeScheme#constructJoinGroupCodeStr(String, String)
     */
    @Override
    protected void initDataFromIntent() {
        // 解析从intent中传过来的数据
        ArrayList intentDatas = IntentFactory.parseJoinGroupIntent(getIntent());
        // 群2维码内容组织，请见QRCodeScheme.constructJoinGroupCodeStr()方法
        String qrcodeValue = (String)intentDatas.get(0);
        if (qrcodeValue != null) {
            try {
                // 群id
                gid = qrcodeValue.substring(0, qrcodeValue.lastIndexOf("_") );
                // 群二维码分享者的uid
                sharedByUid = qrcodeValue.substring(qrcodeValue.lastIndexOf("_") + 1);
                Log.v(TAG, "initDataFromIntent中：gid="+gid+", sharedByUid="+sharedByUid);
            } catch (Exception e) {
                Log.w(TAG, e);
            }
        }

        joinBy = (int)intentDatas.get(1);
    }

    /**
     * 本方法由父类的onCreate()调用，子类可在此方法中实现自已的UI显示逻辑。
     * 
     * @see #init(Bundle)
     */
    @Override
    protected void initViews(Bundle savedInstanceState) {
        // 设定自定义标题栏（设定此值即意味着开启自定义标题栏的使用，必须要在setContentView前设定）
        customeTitleBarResId = R.id.groupchat_join_group_title_bar;
        // 养成良好习惯：首先设置主layout，确保后绪的操作中使用到的组件都可以被find到
        setContentView(R.layout.groupchat_join_group_activity);

        // 初始化各种组件
        viewIcon = findViewById(R.id.groupchat_join_group_imageView);
        viewName = findViewById(R.id.groupchat_join_group_nameView);
        viewDesc = findViewById(R.id.groupchat_join_group_descView);
        btnOk = findViewById(R.id.groupchat_join_group_okBtn);

        this.setTitle($$(R.string.join_group_activity_title));
        this.setLoadDataOnCreate(false);

        // 检查传进来的参数合法性
        if(CommonUtils.isStringEmpty(gid, true)
                ||  CommonUtils.isStringEmpty(sharedByUid, true)){
            Log.w(TAG, "无效的群id="+gid+"、sharedByUid="+sharedByUid+"(joinBy="+joinBy+")！");
            promtAndFinish($$(R.string.join_group_activity_invalid_qrcode));
        }
        else{
            initDatas();
        }
    }

    /**
     * 初始化界面数据显示等。
     */
    protected void initDatas(){
        // 加群群头像
        loadGroupIcon();

        // 如果已经加入了该群，则直接用缓存的群信息刷新ui数据显示（缓存列表中能找到该群信息即可认为已加入该群）
        GroupEntity ge = MyApplication.getInstance2().getIMClientManager().getGroupsProvider().getGroupInfoByGid(gid);
        if(ge != null){
            btnOk.setText($$(R.string.join_group_activity_btn_text1));
            btnOk.setBackgroundResource(R.drawable.common_btn_lightgray_weixin_2019);
            btnOk.setTextColor(getResources().getColor(R.color.common_list_light_red_for_text));
            resreshDatas(ge);
        }
        // 如果没加入过该群，则通过网络加载该群基本信息
        else{
            btnOk.setText($$(R.string.join_group_activity_btn_text2));
            btnOk.setBackgroundResource(R.drawable.common_btn_lightred_2019);
            btnOk.setTextColor(getResources().getColor(R.color.white));
            // 将通过 queryData 方法从服务端获取数据，并通过 refreshToView方法将返回的数据显示的ui上
            this.setLoadDataOnCreate(true);
        }

        // 如果群分享的人是本地用户自已（则直接读取本地用户信息缓存）
        if(sharedByUid != null && sharedByUid.equals(lu().getUser_uid())){
            this.sharedByUser = lu();
            Log.v(TAG, "分享者正是本地用户自已：sharedByUid="+sharedByUid);
        }
        // 如果群分享的人是好友（则直接从好友缓存列表中读取用户信息）
        else if(MyApplication.getInstance2().getIMClientManager().getFriendsListProvider().isUserInRoster2(sharedByUid)){
            this.sharedByUser = MyApplication.getInstance2().getIMClientManager().getFriendsListProvider().getFriendInfoByUid2(sharedByUid);
            Log.v(TAG, "分享者是好友：sharedByUid="+sharedByUid+"，sharedByUser="+sharedByUser);
        }
        // 以上情况都不是，那就只能从网格加载该分享者的基础信息
        else{
            Log.v(TAG, "分享者是陌生人，马上开始从网络加载......");
            this.viewModel.loadSharedByUserInfo(sharedByUid);
        }

        // 通过LiveData的观察者机制，实现群基本信息数据加载完成的通知，以便即时在ui显示出来
        this.viewModel.getGroupInfoLiveData().observe(this, this::queryDataAfter);
        // 通过LiveData的观察者机制，实现2维码分享者基本信息数据加载完成的处理
        this.viewModel.getSharedByUserInfoLiveData().observe(this, this::processLoadedSharedByUserInfo);
        // 通过LiveData的观察者机制，实现加群请求结果的处理
        this.viewModel.getJoinGroupSubmitLiveData().observe(this, this::processJoinGroupResult);
    }

    /**
     * 本方法由父类的onCreate()调用，子类可在此方法中为各UI功能组件增加事件临听。
     */
    @Override
    protected void initListeners() {
        btnOk.setOnClickListener(v -> {
            // 如果已经加入了该群，则直接进入群聊（缓存列表中能找到该群信息即可认为已加入该群）
            GroupEntity ge = MyApplication.getInstance2().getIMClientManager().getGroupsProvider().getGroupInfoByGid(gid);
            if(ge != null){
                // 直接进入群聊聊天界面
                startActivity(IntentFactory.createGroupChatIntent(self(), ge.getG_id(), ge.getG_name()));
                finish();
            }
            // 不存在该群信息，即表示尚未加入该群
            else{
                showProgress($$(R.string.join_group_activity_join_loading));
                // 异步提交加群请求
                viewModel.submitJoinGroup(gid, sharedByUid, sharedByUser == null?sharedByUid:sharedByUser.getNickname(), joinBy);
            }
        });
    }

    /**
     * 分享者基本信息通过ViewModel从网络异步加载完成后的处理逻辑。
     *
     * @param dataFromServer 服务端返回的http接口请求结果
     */
    private void processLoadedSharedByUserInfo(DataFromServer dataFromServer){
        if(dataFromServer != null && dataFromServer.isSuccess()){
            Object jsonOfResult = dataFromServer.getReturnValue();
            if(jsonOfResult != null) {
                sharedByUser = HttpRestHelper.parseGetFriendInfoFromServer((String) jsonOfResult);
            }
            else{
                Log.w(TAG, "processLoadedSharedByUserInfo中jsonOfResult=null!");
            }
        }
        else{
            Log.w(TAG, "processLoadedSharedByUserInfo中无法解析result内容，因为dataFromServer="+dataFromServer
                    +"， dataFromServer.isSuccess()?"+dataFromServer.isSuccess());
        }
    }

    /**
     * 加群请求成功返回后的处理逻辑（加群请求接口返回数据内容请见http"【接口1016-24-24】"手册或代码说明）。
     *
     * @param dataFromServer 服务端返回的http接口请求结果
     */
    private void processJoinGroupResult(DataFromServer dataFromServer){
        hideProgress();
        if(dataFromServer != null){
            // 服务端数据成功返回
            if (checkResultValid(dataFromServer)) {
                System.out.println("--成功");

                // 加群是否成功（true表示加群成功）
                boolean joinSucess = "1".equals((String)dataFromServer.getReturnValue());
                if (joinSucess && groupInfo != null) {
                    // 将刚成功加入的群聊基本信息对象放入本地群聊列表缓存中
                    MyApplication.getInstance2().getIMClientManager().getGroupsProvider().putGroup(groupInfo);
                    // 更新群信息里的群成员数+1
                    GroupMemberActivity.updateCurrentGroupMemberGroupAfterSubmit(self(), gid, 1);
                    // 往聊天界面中显示一条被"我"通过扫描二维码加入群聊成功这样的提示信息（此通知并非服务器发出，而是本地准备好的，仅用UI显示）
                    GChatDataHelper.addSystemInfo_joinGroupSucess(self(), joinBy
                            , sharedByUser == null ? null : sharedByUser.getNickname()//sharedByUser.getNickNameWithRemark()
                            , gid, groupInfo.getG_name(), CommonUtils.getIntValue(groupInfo.getG_member_count()));

                    // 刷新群头像的更新时间戳，关于群头像的缓存更新逻辑，请见 GroupsProvider.refreshGroupImageUpdateTimestamp(..)方法的说明
                    MyApplication.getInstance2().getIMClientManager().getGroupsProvider().refreshGroupImageUpdateTimestamp(groupInfo);
                    // toast提示
                    WidgetUtils.showToast(this, $$(R.string.join_group_activity_join_sucess), WidgetUtils.ToastType.OK);
                    // 进入刚加入的这个群聊聊天界面
                    startActivity(IntentFactory.createGroupChatIntent(self(), gid, groupInfo.getG_name()));
                    // 退出当前界面
                    finish();
                } else {
                    Log.w(TAG, "扫码加群失败，原因是：joinSucess="+joinSucess+"， groupInfo="+groupInfo);
                    WidgetUtils.showToast(this, R.string.join_group_activity_join_fail, WidgetUtils.ToastType.WARN);
                }
            }
        }
    }

    /**
     * 将群基本信息显示在ui上。
     *
     * @param ge 群基本信息
     */
    private void resreshDatas(GroupEntity ge){
        if(ge != null){
            this.viewName.setText(ge.getG_name());
            this.viewDesc.setText(ToolKits.i18n(self(), R.string.join_group_activity_group_member_count, ge.getG_member_count()));
        }
    }

    /**
     * 异步加载群头像.
     */
    public void loadGroupIcon(){
        // 加载群头像
        ImageCacheLoader.loadGroupImgWithGlide(Glide.with(this), gid, viewIcon, 7 , false, R.drawable.groupchat_groups_icon_default_r21px);
    }

    /**
     * 通过网络加载群基本信息。
     *
     * @param showProgress 由{@link #loadData(boolean, String)}传过来的参数
     * @param progressMsg 由{@link #loadData(boolean, String)}传过来的参数
     * @return 网络返回的原始数据对象
     */
    @Override
    protected void queryData(boolean showProgress, String progressMsg) {
        super.queryData(showProgress, progressMsg);
        // 从网络加载群基本信息数据
        viewModel.loadGroupInfo(gid);
    }

    /**
     * 网络加载完成后的群基本信息数据处理逻辑（用于UI显示等）。
     *
     * @param jsonOfResult 网络返回的数据内容
     */
    @Override
    protected void refreshToView(String jsonOfResult) {
        GroupEntity groupInfo;
        //服务端返回的用户信息不为空，即证明该用户存在，否则表示不存在该用户
        if (jsonOfResult != null && (groupInfo = HttpRestHelper.parseGetGroupInfoFromServer((String) jsonOfResult)) != null) {
            this.groupInfo = groupInfo;
            this.resreshDatas(groupInfo);
        }
        else{
            promtAndFinish($$(R.string.join_group_activity_group_not_exists));
        }
    }

    private void promtAndFinish(String promtMsg){
        new AlertDialog.Builder(this)
                .setTitle(this.getResources().getString(R.string.general_error))
                .setMessage(promtMsg)
                .setPositiveButton(this.getResources().getString(R.string.general_ok), (dialog, which) -> self().finish())
                .setCancelable(false)
                .show();
    }
}
